from typing import TypeVar

from zkl_pyutils_registries.basics import Matcher, NotMatched

T = TypeVar('T')


class SubTypeMatcher(Matcher[type[T], type[T], int]):
    """ Matches if the key is a subclass of the query """

    def match(self, query: type[T], key: type[T]) -> int:
        return match_type(key, query)


class SupTypeMatcher(Matcher[type[T], type[T], int]):
    """ Matches if the key is a superclass of the query """

    def match(self, query: type[T], key: type[T]) -> int:
        return match_type(query, key)


def match_type(sub_type: type, sup_type: type) -> int:
    if not issubclass(sub_type, sup_type):
        raise NotMatched
    mro = type.mro(sub_type)
    try:
        return -mro.index(sup_type)
    except ValueError:  # protocol
        return -len(mro)
